import { User } from './../../interfaces/request.interface';
import { config } from 'process';
import { ConfigService } from '@nestjs/config';
import { WxMiniLoginDto } from './dto/wxMiniLogin.dto';
import { toDataUTCTime } from './../../utils/timeUtil';
import { LoginDto } from './dto/login.dto';
import { CommonRedisService } from './../common-redis/common-redis.service';
import { UserEntity } from './../../entity/user.entity';
import { CreateUserDto } from './dto/createUser.dto';
import { AuthService } from '../auth/auth.service';
import { Injectable, HttpStatus, HttpException, Inject, forwardRef } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as svgCaptcha from 'svg-captcha'
import { v4 as uuidv4 } from 'uuid';
import { ApiConfig, MiniProgramApi, ApiConfigKit, Kits } from 'tnwx';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class UserService {
    constructor(
        @InjectRepository(UserEntity) private readonly userRep: Repository<UserEntity>,
        @Inject(forwardRef(() => AuthService))
        private readonly authServ: AuthService,
        private readonly commonRedisServ: CommonRedisService,
        private readonly configServ: ConfigService
    ) {
        // 设置当前的微信应用的AppId
        const myMiniAppConfig: ApiConfig = this.configServ.get('WX_CONFIG')['myMiniApp'];
        ApiConfigKit.setCurrentAppId(myMiniAppConfig.getAppId);
    }

    /**
     *  微信小程序登陆
     */
    async wxMinilogin(dto: WxMiniLoginDto): Promise<any> {
        const data = await MiniProgramApi.code2Session(ApiConfigKit.getAppId, ApiConfigKit.getApiConfig.getAppScrect, dto.code);
        console.log(data);
        if (!data.session_key || !data.openid) {
            throw new HttpException(JSON.stringify(data), HttpStatus.BAD_REQUEST);
        }

        const key = Buffer.from(data.session_key, 'base64');
        const baseIv = Buffer.from(dto.iv, 'base64');
        const ecrypt = Kits.aes128cbcDecrypt(key, baseIv, dto.encryptedData);
        console.log("🚀 ~ file: user.service.ts ~ line 40 ~ UserService ~ wxMinilogin ~ ecrypt", ecrypt)
        return { data: JSON.parse(ecrypt) };
    }

    /**
     * 普通账号密码登录
     */
    async login(loginDto: LoginDto): Promise<any> {
        const { username, password } = loginDto;
        const user = await this.findOneByUsername(username)
        if (!user) {
            throw new HttpException({ message: '用户名不存在！' }, HttpStatus.BAD_REQUEST);
        }
        if (user.password !== password) {
            throw new HttpException({ message: '密码错误！' }, HttpStatus.BAD_REQUEST);
        }
        await this.userRep
            .createQueryBuilder()
            .update(UserEntity)
            .set({
                lastLoginTime: toDataUTCTime(new Date())
            })
            .where("id = :id", { id: user.id })
            .execute()

        const payload: User = { username: user.username, id: user.id, type: 'user' };
        return { accessToken: this.authServ.sign(payload) }
    }

    async addOne(userDto: CreateUserDto): Promise<any> {
        const { username, password, phone, captcha, uuid } = userDto;
        const redisCaptcha = await this.commonRedisServ.get(uuid);

        if (redisCaptcha !== captcha.toLocaleLowerCase()) {
            throw new HttpException({ message: '验证码错误！' }, HttpStatus.BAD_REQUEST);
        }
        const user = await this.findOneByUsername(username)
        if (user) {
            throw new HttpException({ message: '用户名已存在！' }, HttpStatus.BAD_REQUEST);
        }

        const userEty = new UserEntity;
        userEty.username = username;
        userEty.password = password;
        userEty.phone = phone;
        await this.userRep.save(userEty)
        return { message: '注册成功!' };
    }

    // 生成图像验证码
    async genCaptcha(): Promise<any> {
        const captcha = svgCaptcha.create({
            ignoreChars: '0o1il',
            noise: 1,
            color: true,
        })
        const uuid = uuidv4()
        await this.commonRedisServ.set(uuid, captcha.text.toLowerCase())
        return {
            uuid,
            img: captcha.data
        }
    }

    async getCaptcha(): Promise<any> {
        const captcha = await this.commonRedisServ.get('test')
        return { captcha };
    }

    async findOneByUsername(username: string): Promise<UserEntity> {
        return this.userRep.findOne({ username })
    }

    async findById(userId: string): Promise<UserEntity> {
        return this.userRep.findOne({ id: userId })
    }

}
